﻿using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Xml;
using ZoneFiveSoftware.Common.Data.Fitness;
using ZoneFiveSoftware.Common.Data.Measurement;
using ZoneFiveSoftware.Common.Visuals.Fitness;
using STCommon.Data;
using STCommon.View;

namespace DistributionPlugin.Controller
{
    public class ApplicationOptions
    {
        private ApplicationOptions()
        {
        }

        public float MaximumPaceAllowedMetersPerSecond
        {
            get { return m_MaximumPaceAllowedMetersPerSecond; }
/*            set
            {
                if (MaximumPaceAllowedMetersPerSecond != value)
                {
                    m_MaximumPaceAllowedMetersPerSecond = value;

                    TriggerOptionChanged("MaximumPaceAllowedMetersPerSecond");
                }
            }*/
        }

        public static ApplicationOptions Instance
        {
            get
            {
                if (m_Instance == null)
                {
                    m_Instance = new ApplicationOptions();
                }

                return m_Instance;
            }
        }

        private void TriggerOptionChanged(String propertyName)
        {
            if (OptionChanged != null)
            {
                OptionChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        public event PropertyChangedEventHandler OptionChanged;

        private static ApplicationOptions m_Instance = null;

        private float m_MaximumPaceAllowedMetersPerSecond = 0.83333333333333f;
    }

    public class DistributionOptions
    {
        protected DistributionOptions()
        {
        }

        public virtual void LoadFromXml(XmlNode parentNode)
        {
            if (parentNode != null)
            {
                foreach (XmlNode currentChild in parentNode.ChildNodes)
                {
                    try
                    {
                        switch (currentChild.Name)
                        {
                            case SelectedDataTypeXmlNodeName:
                                {
                                    int value = int.Parse(currentChild.FirstChild.Value);

                                    if (value < (int)Enums.SportTracksDataTrackTypes.DataTrackTypeCount)
                                    {
                                        SelectedDataType = (Enums.SportTracksDataTrackTypes)value;
                                    }
                                    break;
                                }
                            case SelectedReferentialXmlNodeName:
                                {
                                    int value = int.Parse(currentChild.FirstChild.Value);

                                    if (value < (int)Enums.SportTracksXAxisReferential.ReferentialCount)
                                    {
                                        SelectedReferential = (Enums.SportTracksXAxisReferential)value;
                                    }
                                    break;
                                }
                            case HeartRateReferentialXmlNodeName:
                                {
                                    int value = int.Parse(currentChild.FirstChild.Value);

                                    if (value <= (int)HeartRate.PercentTypes.PercentOfReserve)
                                    {
                                        HeartRateReferential = (HeartRate.PercentTypes)value;
                                    }
                                    break;
                                }
                            case TreeListSerializerXmlNodeName:
                                {
                                    TreeListSerializer.LoadFromSettings(currentChild);
                                    break;
                                }
                            case CadenceIntervalLengthXmlNodeName:
                                {
                                    CadenceIntervalLength = float.Parse(currentChild.FirstChild.Value);
                                    break;
                                }
                            case ElevationIntervalLengthXmlNodeName:
                                {
                                    ElevationIntervalLength = float.Parse(currentChild.FirstChild.Value);
                                    break;
                                }
                            case GradeIntervalLengthXmlNodeName:
                                {
                                    GradeIntervalLength = float.Parse(currentChild.FirstChild.Value);
                                    break;
                                }
                            case HeartRateBPMIntervalLengthXmlNodeName:
                                {
                                    HeartRateBPMIntervalLength = float.Parse(currentChild.FirstChild.Value);
                                    break;
                                }
                            case HeartRatePercentIntervalLengthXmlNodeName:
                                {
                                    HeartRatePercentIntervalLength = float.Parse(currentChild.FirstChild.Value);
                                    break;
                                }
                            case SpeedIntervalLengthXmlNodeName:
                                {
                                    SpeedIntervalLength = float.Parse(currentChild.FirstChild.Value);
                                    break;
                                }
                            case PaceIntervalLengthXmlNodeName:
                                {
                                    PaceIntervalLength = float.Parse(currentChild.FirstChild.Value);
                                    break;
                                }
                            case PowerIntervalLengthXmlNodeName:
                                {
                                    PowerIntervalLength = float.Parse(currentChild.FirstChild.Value);
                                    break;
                                }
                            case ActiveLapsOnlyXmlNodeName:
                                {
                                    ActiveLapsOnly = bool.Parse(currentChild.FirstChild.Value);
                                    break;
                                }
                            default:
                                {
                                    break;
                                }
                        }
                    }
                    catch
                    {
                        // Ignore the error, it's probably a parsing error
                    }
                }
            }
        }

        public virtual void SaveToXml(XmlDocument xmlDoc, XmlNode parentNode, String childNodeName)
        {
            if (xmlDoc != null && parentNode != null &&
                !String.IsNullOrEmpty(childNodeName))
            {
                XmlNode masterNode = xmlDoc.CreateElement(childNodeName);
                XmlNode optionNode;

                parentNode.AppendChild(masterNode);

                // Selected data type
                optionNode = xmlDoc.CreateElement(SelectedDataTypeXmlNodeName);
                masterNode.AppendChild(optionNode);
                optionNode.AppendChild(xmlDoc.CreateTextNode(((int)SelectedDataType).ToString()));

                // Selected referential
                optionNode = xmlDoc.CreateElement(SelectedReferentialXmlNodeName);
                masterNode.AppendChild(optionNode);
                optionNode.AppendChild(xmlDoc.CreateTextNode(((int)SelectedReferential).ToString()));

                // HR referential
                optionNode = xmlDoc.CreateElement(HeartRateReferentialXmlNodeName);
                masterNode.AppendChild(optionNode);
                optionNode.AppendChild(xmlDoc.CreateTextNode(((int)HeartRateReferential).ToString()));

                // Tree list options
                TreeListSerializer.SaveToSettings(xmlDoc, masterNode, TreeListSerializerXmlNodeName);

                // Cadence interval
                optionNode = xmlDoc.CreateElement(CadenceIntervalLengthXmlNodeName);
                masterNode.AppendChild(optionNode);
                optionNode.AppendChild(xmlDoc.CreateTextNode(CadenceIntervalLength.ToString()));

                // Elevation interval
                optionNode = xmlDoc.CreateElement(ElevationIntervalLengthXmlNodeName);
                masterNode.AppendChild(optionNode);
                optionNode.AppendChild(xmlDoc.CreateTextNode(ElevationIntervalLength.ToString()));

                // Grade interval
                optionNode = xmlDoc.CreateElement(GradeIntervalLengthXmlNodeName);
                masterNode.AppendChild(optionNode);
                optionNode.AppendChild(xmlDoc.CreateTextNode(GradeIntervalLength.ToString()));

                // HR BPM interval
                optionNode = xmlDoc.CreateElement(HeartRateBPMIntervalLengthXmlNodeName);
                masterNode.AppendChild(optionNode);
                optionNode.AppendChild(xmlDoc.CreateTextNode(HeartRateBPMIntervalLength.ToString()));

                // HR% interval
                optionNode = xmlDoc.CreateElement(HeartRatePercentIntervalLengthXmlNodeName);
                masterNode.AppendChild(optionNode);
                optionNode.AppendChild(xmlDoc.CreateTextNode(HeartRatePercentIntervalLength.ToString()));

                // Speed interval
                optionNode = xmlDoc.CreateElement(SpeedIntervalLengthXmlNodeName);
                masterNode.AppendChild(optionNode);
                optionNode.AppendChild(xmlDoc.CreateTextNode(SpeedIntervalLength.ToString()));

                // Pace interval
                optionNode = xmlDoc.CreateElement(PaceIntervalLengthXmlNodeName);
                masterNode.AppendChild(optionNode);
                optionNode.AppendChild(xmlDoc.CreateTextNode(PaceIntervalLength.ToString()));

                // Power interval
                optionNode = xmlDoc.CreateElement(PowerIntervalLengthXmlNodeName);
                masterNode.AppendChild(optionNode);
                optionNode.AppendChild(xmlDoc.CreateTextNode(PowerIntervalLength.ToString()));

                // Active laps only
                optionNode = xmlDoc.CreateElement(ActiveLapsOnlyXmlNodeName);
                masterNode.AppendChild(optionNode);
                optionNode.AppendChild(xmlDoc.CreateTextNode(ActiveLapsOnly.ToString()));
            }
        }

        public TreeListOptionsSerializer TreeListSerializer
        {
            get { return m_TreeListSerializer; }
        }

        public Enums.SportTracksDataTrackTypes SelectedDataType
        {
            get { return m_SelectedDataType; }
            set
            {
                if (SelectedDataType != value)
                {
                    m_SelectedDataType = value;

                    TriggerOptionChanged("SelectedDataType");
                }
            }
        }

        public Enums.SportTracksXAxisReferential SelectedReferential
        {
            get { return m_SelectedReferential; }
            set
            {
                if (SelectedReferential != value)
                {
                    m_SelectedReferential = value;

                    TriggerOptionChanged("SelectedReferential");
                }
            }
        }

        public HeartRate.PercentTypes HeartRateReferential
        {
            get { return m_HeartRateReferential; }
            set
            {
                if (HeartRateReferential != value)
                {
                    m_HeartRateReferential = value;

                    TriggerOptionChanged("HeartRateReference");
                }
            }
        }

        public float SelectedDataTypeIntervalLength
        {
            get
            {
                switch(SelectedDataType)
                {
                    case Enums.SportTracksDataTrackTypes.Cadence:
                    {
                        return CadenceIntervalLength;
                    }
                    case Enums.SportTracksDataTrackTypes.Elevation:
                    {
                        return ElevationIntervalLength;
                    }
                    case Enums.SportTracksDataTrackTypes.Grade:
                    {
                        return GradeIntervalLength;
                    }
                    case Enums.SportTracksDataTrackTypes.HeartRate:
                    {
                        switch (HeartRateReferential)
                        {
                            case HeartRate.PercentTypes.None:
                            {
                                return HeartRateBPMIntervalLength;
                            }
                            case HeartRate.PercentTypes.PercentOfReserve:
                            case HeartRate.PercentTypes.PercentOfMax:
                            {
                                return HeartRatePercentIntervalLength;
                            }
                            default:
                            {
                                return 0;
                            }
                        }
                    }
                    case Enums.SportTracksDataTrackTypes.Power:
                    {
                        return PowerIntervalLength;
                    }
                    case Enums.SportTracksDataTrackTypes.Speed:
                    {
                        if (m_SpeedReferential == Speed.Units.Speed)
                        {
                            return SpeedIntervalLength;
                        }
                        else
                        {
                            return PaceIntervalLength;
                        }
                    }
                    default:
                    {
                        return 0;
                    }
                }
            }
            set
            {
                switch(SelectedDataType)
                {
                    case Enums.SportTracksDataTrackTypes.Cadence:
                    {
                        CadenceIntervalLength = value;
                        break;
                    }
                    case Enums.SportTracksDataTrackTypes.Elevation:
                    {
                        ElevationIntervalLength = value;
                        break;
                    }
                    case Enums.SportTracksDataTrackTypes.Grade:
                    {
                        GradeIntervalLength = value;
                        break;
                    }
                    case Enums.SportTracksDataTrackTypes.HeartRate:
                    {
                        switch (HeartRateReferential)
                        {
                            case HeartRate.PercentTypes.None:
                            {
                                HeartRateBPMIntervalLength = value;
                                break;
                            }
                            case HeartRate.PercentTypes.PercentOfReserve:
                            case HeartRate.PercentTypes.PercentOfMax:
                            {
                                HeartRatePercentIntervalLength = value;
                                break;
                            }
                            default:
                            {
                                break;
                            }
                        }
                        break;
                    }
                    case Enums.SportTracksDataTrackTypes.Power:
                    {
                        PowerIntervalLength = value;
                        break;
                    }
                    case Enums.SportTracksDataTrackTypes.Speed:
                    {
                        if (m_SpeedReferential == Speed.Units.Speed)
                        {
                            SpeedIntervalLength = value;
                        }
                        else
                        {
                            PaceIntervalLength = value;
                        }
                        break;
                    }
                    default:
                    {
                        break;
                    }
                }
            }
        }

        public float CadenceIntervalLength
        {
            get { return m_CadenceIntervalLength; }
            set
            {
                if (value != CadenceIntervalLength)
                {
                    m_CadenceIntervalLength = value;

                    TriggerOptionChanged("CadenceIntervalLength");
                }
            }
        }

        public float ElevationIntervalLength
        {
            get { return m_ElevationIntervalLength; }
            set
            {
                if (value != ElevationIntervalLength)
                {
                    m_ElevationIntervalLength = value;

                    TriggerOptionChanged("ElevationIntervalLength");
                }
            }
        }

        public float GradeIntervalLength
        {
            get { return m_GradeIntervalLength; }
            set
            {
                if (value != GradeIntervalLength)
                {
                    m_GradeIntervalLength = value;

                    TriggerOptionChanged("GradeIntervalLength");
                }
            }
        }
        
        public float HeartRateBPMIntervalLength
        {
            get { return m_HeartRateBPMIntervalLength; }
            set
            {
                if (value != HeartRateBPMIntervalLength)
                {
                    m_HeartRateBPMIntervalLength = value;

                    TriggerOptionChanged("HeartRateBPMIntervalLength");
                }
            }
        }

        public float HeartRatePercentIntervalLength
        {
            get { return m_HeartRatePercentIntervalLength; }
            set
            {
                if (value != HeartRatePercentIntervalLength)
                {
                    m_HeartRatePercentIntervalLength = value;

                    TriggerOptionChanged("HeartRatePercentIntervalLength");
                }
            }
        }

        public float SpeedIntervalLength
        {
            get { return m_SpeedIntervalLength; }
            set
            {
                if (value != SpeedIntervalLength)
                {
                    m_SpeedIntervalLength = value;

                    TriggerOptionChanged("SpeedIntervalLength");
                }
            }
        }

        public float PaceIntervalLength
        {
            get { return m_PaceIntervalLength; }
            set
            {
                if (value != PaceIntervalLength)
                {
                    m_PaceIntervalLength = value;

                    TriggerOptionChanged("PaceIntervalLength");
                }
            }
        }

        public Speed.Units SpeedReferential
        {
            get { return m_SpeedReferential; }
            set
            {
                if (value != SpeedReferential)
                {
                    m_SpeedReferential = value;

                    TriggerOptionChanged("SpeedReferential");
                }
            }
        }

        public float PowerIntervalLength
        {
            get { return m_PowerIntervalLength; }
            set
            {
                if (value != PowerIntervalLength)
                {
                    m_PowerIntervalLength = value;

                    TriggerOptionChanged("PowerIntervalLength");
                }
            }
        }

        public bool ActiveLapsOnly
        {
            get { return m_ActiveLapsOnly; }
            set
            {
                if (value != ActiveLapsOnly)
                {
                    m_ActiveLapsOnly = value;

                    TriggerOptionChanged("ActiveLapsOnly");
                }
            }
        }
        protected void TriggerOptionChanged(String propertyName)
        {
            if (OptionChanged != null)
            {
                OptionChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        public event PropertyChangedEventHandler OptionChanged;

        private const string SelectedDataTypeXmlNodeName = "SelectedDataType";
        private const string SelectedReferentialXmlNodeName = "SelectedReferential";
        private const string HeartRateReferentialXmlNodeName = "HeartRateReferential";
        private const string TreeListSerializerXmlNodeName = "TreeListOptions";
        private const string CadenceIntervalLengthXmlNodeName = "CadenceIntervalLength";
        private const string ElevationIntervalLengthXmlNodeName = "ElevationIntervalLength";
        private const string GradeIntervalLengthXmlNodeName = "GradeIntervalLength";
        private const string HeartRateBPMIntervalLengthXmlNodeName = "HeartRateBPMIntervalLength";
        private const string HeartRatePercentIntervalLengthXmlNodeName = "HeartRatePercentIntervalLength";
        private const string SpeedIntervalLengthXmlNodeName = "SpeedIntervalLength";
        private const string PaceIntervalLengthXmlNodeName = "PaceIntervalLength";
        private const string PowerIntervalLengthXmlNodeName = "PowerIntervalLength";
        private const string ActiveLapsOnlyXmlNodeName = "ActiveLapsOnly";

        private Enums.SportTracksDataTrackTypes m_SelectedDataType = Enums.SportTracksDataTrackTypes.HeartRate;
        private Enums.SportTracksXAxisReferential m_SelectedReferential = Enums.SportTracksXAxisReferential.Time;
        private Speed.Units m_SpeedReferential = Speed.Units.Speed;
        private HeartRate.PercentTypes m_HeartRateReferential = HeartRate.PercentTypes.None;
        private TreeListOptionsSerializer m_TreeListSerializer = new TreeListOptionsSerializer();
        private float m_CadenceIntervalLength = 15;
        private float m_ElevationIntervalLength = 50;
        private float m_GradeIntervalLength = 1;
        private float m_HeartRateBPMIntervalLength = 10;
        private float m_HeartRatePercentIntervalLength = 5;
        private float m_SpeedIntervalLength = 2.5f;
        private float m_PaceIntervalLength = 2.5f;
        private float m_PowerIntervalLength = 25;
        private bool m_ActiveLapsOnly = false;
    }

    public class ActivityDetailsOptions : DistributionOptions
    {
        private ActivityDetailsOptions()
        {
        }

        public override void LoadFromXml(XmlNode parentNode)
        {
            base.LoadFromXml(parentNode);

            if (parentNode != null)
            {
                foreach (XmlNode currentChild in parentNode.ChildNodes)
                {
                    try
                    {
                        switch (currentChild.Name)
                        {
                            case ChartSplitSizeXmlNodeName:
                                {
                                    ChartSplitSize = int.Parse(currentChild.FirstChild.Value);
                                    break;
                                }
                            default:
                                {
                                    break;
                                }
                        }
                    }
                    catch
                    {
                        // Ignore the error, it's probably a parsing error
                    }
                }
            }
        }

        public override void SaveToXml(XmlDocument xmlDoc, XmlNode parentNode, String childNodeName)
        {
            base.SaveToXml(xmlDoc, parentNode, childNodeName);

            if (xmlDoc != null && parentNode != null &&
                !String.IsNullOrEmpty(childNodeName))
            {
                XmlNode masterNode = parentNode.LastChild;
                XmlNode optionNode;

                // Chart split size
                optionNode = xmlDoc.CreateElement(ChartSplitSizeXmlNodeName);
                masterNode.AppendChild(optionNode);
                optionNode.AppendChild(xmlDoc.CreateTextNode(ChartSplitSize.ToString()));
            }
        }

        public static ActivityDetailsOptions CreateInstance()
        {
            return new ActivityDetailsOptions();
        }

        public static ActivityDetailsOptions DailyActivityInstance
        {
            get
            {
                if (m_DailyActivityInstance == null)
                {
                    m_DailyActivityInstance = CreateInstance();
                }

                return m_DailyActivityInstance;
            }
        }

        public static ActivityDetailsOptions ReportsActivityInstance
        {
            get
            {
                if (m_ReportsActivityInstance == null)
                {
                    m_ReportsActivityInstance = CreateInstance();
                }

                return m_ReportsActivityInstance;
            }
        }

        public int ChartSplitSize
        {
            get { return m_ChartSplitSize; }
            set
            {
                if (value != ChartSplitSize)
                {
                    m_ChartSplitSize = value;

                    TriggerOptionChanged("ChartSplitSize");
                }
            }
        }

        private const string ChartSplitSizeXmlNodeName = "ChartSplitSize";

        private static ActivityDetailsOptions m_DailyActivityInstance = null;
        private static ActivityDetailsOptions m_ReportsActivityInstance = null;

        private int m_ChartSplitSize = 250;
    }

    public class ReportPageOptions
    {
        private ReportPageOptions()
        {
            m_ReportPanelsOptions = new ReportOptions[ReportPageOptions.MaxPanelCount];

            for (int i = 0; i < ReportPageOptions.MaxPanelCount; ++i)
            {
                m_ReportPanelsOptions[i] = ReportOptions.CreateInstance();
            }
        }

        public ReportOptions GetPanelOptions(int index)
        {
            Debug.Assert(index >= 0 && index < m_ReportPanelsOptions.Length);

            return m_ReportPanelsOptions[index];
        }

        public int GetPanelOptionsIndex(ReportOptions options)
        {
            for (int i = 0; i < ReportPageOptions.MaxPanelCount; ++i)
            {
                if (m_ReportPanelsOptions[i] == options)
                {
                    return i;
                }
            }

            // Not found
            return -1;
        }

        public void LoadFromReport(IActivityReport report)
        {
            string reportData = report.GetExtensionText(GUIDs.PluginMain);
            XmlDocument xmlDoc = new XmlDocument();

            try
            {
                xmlDoc.LoadXml(reportData);
                LoadFromXml(xmlDoc.FirstChild);
            }
            catch
            {
                // We probably failed to load the data from the report
            }
        }

        public void LoadFromXml(XmlNode parentNode)
        {
            if (parentNode != null)
            {
                foreach (XmlNode currentChild in parentNode.ChildNodes)
                {
                    try
                    {
                        switch (currentChild.Name)
                        {
                            case DisplayedPanelsCountXmlNodeName:
                                {
                                    DisplayedPanelsCount = int.Parse(currentChild.FirstChild.Value);
                                    break;
                                }
                            case FirstPanelOptionsXmlNodeName:
                                {
                                    m_ReportPanelsOptions[0].LoadFromXml(currentChild);
                                    break;
                                }
                            case SecondPanelOptionsXmlNodeName:
                                {
                                    m_ReportPanelsOptions[1].LoadFromXml(currentChild);
                                    break;
                                }
                            case ThirdPanelOptionsXmlNodeName:
                                {
                                    m_ReportPanelsOptions[2].LoadFromXml(currentChild);
                                    break;
                                }
                            case FourthPanelOptionsXmlNodeName:
                                {
                                    m_ReportPanelsOptions[3].LoadFromXml(currentChild);
                                    break;
                                }
                            default:
                                {
                                    break;
                                }
                        }
                    }
                    catch
                    {
                        // Ignore the error, it's probably a parsing error
                    }
                }
            }
        }

        public void SaveToReport(IActivityReport report)
        {
            XmlDocument xmlDoc = new XmlDocument();

            SaveToXml(xmlDoc, xmlDoc, ReportsPageOptionsXmlNodeName);
            report.SetExtensionText(GUIDs.PluginMain, xmlDoc.InnerXml);
        }

        public void SaveToXml(XmlDocument xmlDoc, XmlNode parentNode, String childNodeName)
        {
            if (xmlDoc != null && parentNode != null &&
                !String.IsNullOrEmpty(childNodeName))
            {
                XmlNode masterNode = xmlDoc.CreateElement(childNodeName);
                XmlNode optionNode;

                parentNode.AppendChild(masterNode);

                // Number of displayed panels
                optionNode = xmlDoc.CreateElement(DisplayedPanelsCountXmlNodeName);
                masterNode.AppendChild(optionNode);
                optionNode.AppendChild(xmlDoc.CreateTextNode(DisplayedPanelsCount.ToString()));

                // Panel options
                m_ReportPanelsOptions[0].SaveToXml(xmlDoc, masterNode, FirstPanelOptionsXmlNodeName);
                m_ReportPanelsOptions[1].SaveToXml(xmlDoc, masterNode, SecondPanelOptionsXmlNodeName);
                m_ReportPanelsOptions[2].SaveToXml(xmlDoc, masterNode, ThirdPanelOptionsXmlNodeName);
                m_ReportPanelsOptions[3].SaveToXml(xmlDoc, masterNode, FourthPanelOptionsXmlNodeName);
            }
        }

        public static ReportPageOptions CreateInstance()
        {
            return new ReportPageOptions();
        }

        public static ReportPageOptions Instance
        {
            get
            {
                if(m_Instance == null)
                {
                    m_Instance = CreateInstance();
                }

                return m_Instance;
            }
        }

        public int DisplayedPanelsCount
        {
            get { return m_DisplayedPanelsCount; }
            set
            {
                if (DisplayedPanelsCount != value &&
                    value > 0 && value <= MaxPanelCount)
                {
                    m_DisplayedPanelsCount = value;

                    TriggerOptionChanged("DisplayedPanelsCount");
                }
            }
        }

        protected void TriggerOptionChanged(String propertyName)
        {
            if (OptionChanged != null)
            {
                OptionChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
        
        public event PropertyChangedEventHandler OptionChanged;

        public const int MaxPanelCount = 4;
        private const String ReportsPageOptionsXmlNodeName = "ReportsPageOptions";
        private const String DisplayedPanelsCountXmlNodeName = "DisplayedPanelsCount";
        private const String FirstPanelOptionsXmlNodeName = "FirstPanelOptions";
        private const String SecondPanelOptionsXmlNodeName = "SecondPanelOptions";
        private const String ThirdPanelOptionsXmlNodeName = "ThirdPanelOptions";
        private const String FourthPanelOptionsXmlNodeName = "FourthPanelOptions";

        private static ReportPageOptions m_Instance = null;

        private ReportOptions[] m_ReportPanelsOptions;
        private int m_DisplayedPanelsCount = 2;
    }

    public class ReportOptions : DistributionOptions
    {
        private ReportOptions()
        {
        }

        public override void LoadFromXml(XmlNode parentNode)
        {
            base.LoadFromXml(parentNode);

            if (parentNode != null)
            {
                foreach (XmlNode currentChild in parentNode.ChildNodes)
                {
                    try
                    {
                        switch (currentChild.Name)
                        {
                            case ListModeXmlNodeName:
                                {
                                    IsInListMode = bool.Parse(currentChild.FirstChild.Value);
                                    break;
                                }
                            default:
                                {
                                    break;
                                }
                        }
                    }
                    catch
                    {
                        // Ignore the error, it's probably a parsing error
                    }
                }
            }
        }

        public override void SaveToXml(XmlDocument xmlDoc, XmlNode parentNode, String childNodeName)
        {
            base.SaveToXml(xmlDoc, parentNode, childNodeName);

            if (xmlDoc != null && parentNode != null &&
                !String.IsNullOrEmpty(childNodeName))
            {
                XmlNode masterNode = parentNode.LastChild;
                XmlNode optionNode;

                // List vs chart mode
                optionNode = xmlDoc.CreateElement(ListModeXmlNodeName);
                masterNode.AppendChild(optionNode);
                optionNode.AppendChild(xmlDoc.CreateTextNode(IsInListMode.ToString()));
            }
        }

        public static ReportOptions CreateInstance()
        {
            return new ReportOptions();
        }

        public bool IsInListMode
        {
            get { return m_IsInListMode; }
            set
            {
                if (value != IsInListMode)
                {
                    m_IsInListMode = value;

                    TriggerOptionChanged("IsInListMode");
                }
            }
        }

        private const string ListModeXmlNodeName = "IsInListMode";

        private bool m_IsInListMode = false;
    }
}
